package com.supermap.fabricsdk;


import org.hyperledger.fabric.sdk.*;
import org.hyperledger.fabric.sdk.security.CryptoSuite;
import org.hyperledger.fabric_ca.sdk.HFCAClient;

import java.io.File;
import java.util.Properties;

/**
 * SmChain 客户端，基于 HFClient 封装。是操作区块链的主入口
 */
public class SmChain {
    public HFClient hfClient;
    private Channel channel;
    private NetworkConfig networkConfig;

    /**
     * 通过 yaml 配置文件实例化
     * @param networkConfigFile 网络配置文件
     */
    private SmChain(String channelName, File networkConfigFile) {
        try {
            networkConfig = NetworkConfig.fromYamlFile(networkConfigFile);

            // peer grpc size = 100M
            String peername = networkConfig.getPeerNames().iterator().next();
            Properties peerProperties = networkConfig.getPeerProperties(peername);
            peerProperties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", 100*1024*1024);
            networkConfig.setPeerProperties(peername, peerProperties);
            // orderer grps size = 100M
            String orderername = networkConfig.getOrdererNames().iterator().next();
            Properties ordererProperties = networkConfig.getOrdererProperties(orderername);
            ordererProperties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", 100*1024*1024);
            networkConfig.setOrdererProperties(orderername, ordererProperties);

            hfClient = HFClient.createNewInstance();
            hfClient.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
            hfClient.setUserContext(networkConfig.getPeerAdmin());
            channel = hfClient.loadChannelFromConfig(channelName, networkConfig);
            channel.initialize();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private SmChain(String channelName, File networkConfigFile, String strName, String strPwd) {
        try {
            this.networkConfig = NetworkConfig.fromYamlFile(networkConfigFile);
            NetworkConfig.CAInfo caInfo = (NetworkConfig.CAInfo)this.networkConfig.getClientOrganization().getCertificateAuthorities().get(0);
            HFCAClient hfcaClient = HFCAClient.createNewInstance(caInfo);
            Enrollment enrollment = hfcaClient.enroll(strName, strPwd);
            NetworkConfig.OrgInfo clientOrg = this.networkConfig.getClientOrganization();
            SmUser user = new SmUser();
            user.setName(strName);
            user.setEnrollment(enrollment);
            user.setMspId(clientOrg.getMspId());
            this.hfClient = HFClient.createNewInstance();
            this.hfClient.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
            this.hfClient.setUserContext(user);
            this.channel = this.hfClient.loadChannelFromConfig(channelName, this.networkConfig);
            this.channel.initialize();
        } catch (Exception var10) {
        }

    }

    /**
     * 自己传参数构造 SmChain
     */
    private SmChain(String channelName, Peer peer, Orderer orderer, User user, HFClient hfClient) {
        try {
            this.hfClient = hfClient;
//            this.hfClient = HFClient.createNewInstance();
            this.hfClient.setUserContext(user);
//            this.hfClient.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
            channel = this.hfClient.newChannel(channelName);
            channel.addPeer(peer);
            channel.addOrderer(orderer);
            channel.initialize();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Channel getHFChannel() {
        return channel;
    }

    HFClient getHfClient(){
        return hfClient;
    }

    public static SmChain getChain(String channelName, Peer peer, Orderer orderer, User user, HFClient hfClient) {
        return new SmChain( channelName, peer, orderer, user, hfClient);
    }

    public static SmChain getChain(String channelName, File blockchainNetworkConfigFile) {
        return new SmChain(channelName, blockchainNetworkConfigFile);
    }

    public static SmChain getChain(String channelName, File networkConfigFile, String strName, String strPwd) {
        return new SmChain(channelName, networkConfigFile, strName, strPwd);
    }

    public SmTransaction getTransaction() {
        return new SmTransactionImp(hfClient, channel);
    }

    public SmChaincode getChaincode() {

        return new SmChaincodeImp(hfClient, channel);
    }

    public SmChannel getChannel() {
        return new SmChannelImp(hfClient, channel);
    }

    public SmCA getCa(String OrgName) {
        return new SmCAImp(networkConfig, OrgName);
    }
}
